package com.jakewharton.mosaic.tty.terminal

import assertk.assertThat
import assertk.assertions.isFalse
import assertk.assertions.isTrue
import kotlin.test.Test

class TtyTerminalSynchronizedOutputTest {
	@Test fun noReply() = terminalTest {
		expect("${CSI}0c", reply = "$CSI?62;22c")
		expect("${CSI}5n", reply = "${CSI}0n")

		val teardown = withTerminal { setup ->
			assertThat(capabilities.synchronizedOutput).isFalse()

			// We make no use of synchronized output directly.
			assertThat(setup).doesNotContain("$CSI?2026h")
		}

		// We make no use of synchronized output directly.
		assertThat(teardown).doesNotContain("$CSI?2026l")
	}

	@Test fun replySet() = terminalTest {
		expect("${CSI}0c", reply = "$CSI?62;22c")
		// Theme events are set (i.e, enabled).
		expect("$CSI?2026\$p", reply = "$CSI?2026;1\$y")
		expect("${CSI}5n", reply = "${CSI}0n")

		val teardown = withTerminal { setup ->
			assertThat(capabilities.synchronizedOutput).isTrue()

			// We make no use of synchronized output directly.
			assertThat(setup).doesNotContain("$CSI?2026h")
		}

		// We make no use of synchronized output directly.
		assertThat(teardown).doesNotContain("$CSI?2026l")
	}

	@Test fun replyReset() = terminalTest {
		expect("${CSI}0c", reply = "$CSI?62;22c")
		// Theme events are reset (i.e, not enabled).
		expect("$CSI?2026\$p", reply = "$CSI?2026;2\$y")
		expect("${CSI}5n", reply = "${CSI}0n")

		val teardown = withTerminal { setup ->
			assertThat(capabilities.synchronizedOutput).isTrue()

			// We make no use of synchronized output directly.
			assertThat(setup).doesNotContain("$CSI?2026h")
		}

		// We make no use of synchronized output directly.
		assertThat(teardown).doesNotContain("$CSI?2026l")
	}

	@Test fun replyPermanentlySet() = terminalTest {
		expect("${CSI}0c", reply = "$CSI?62;22c")
		// Theme events are permanently set (i.e, always enabled).
		expect("$CSI?2026\$p", reply = "$CSI?2026;3\$y")
		expect("${CSI}5n", reply = "${CSI}0n")

		val teardown = withTerminal { setup ->
			// Getting this response is nonsensical, so we treat it like permanently reset.
			assertThat(capabilities.synchronizedOutput).isFalse()

			// We make no use of synchronized output directly.
			assertThat(setup).doesNotContain("$CSI?2026h")
		}

		// We make no use of synchronized output directly.
		assertThat(teardown).doesNotContain("$CSI?2026l")
	}

	@Test fun replyPermanentlyReset() = terminalTest {
		expect("${CSI}0c", reply = "$CSI?62;22c")
		// Theme events are permanently reset (i.e, not supported).
		expect("$CSI?2026\$p", reply = "$CSI?2026;4\$y")
		expect("${CSI}5n", reply = "${CSI}0n")

		val teardown = withTerminal { setup ->
			assertThat(capabilities.synchronizedOutput).isFalse()

			// We make no use of synchronized output directly.
			assertThat(setup).doesNotContain("$CSI?2026h")
		}

		// We make no use of synchronized output directly.
		assertThat(teardown).doesNotContain("$CSI?2026l")
	}
}
